#pragma once

#include <atomic>
#include <memory>
#include <vector>
#include <functional>
#include <mutex>

#include "../utility/Noncopyable.h"
#include "../utility/Timestamp.h"
// #include "../thread/CurrentThread.h"

class Poller;
class Channel;

// EventLoop：reactor；Poller：多路复用器；Channel：事件+事件处理器
// loop封装channel和poller
class EventLoop : Noncopyable
{
public:
    using Callback = std::function<void()>;

    EventLoop();
    ~EventLoop();

    void start();                // 开启事件循环
    void quit();                 // 退出事件循环
    bool isLoopInThread() const; // loop对象是否在自己的线程里
    void wakeupLoopThread();     // 唤醒loop所在线程

    Timestamp getPollReturnTime() const;

    // 执行回调
    // OPTIMIZE: 回调形参传右值引用接左值或右值，不保证回调函数具体内容不用const
    void runCallback(Callback &&cb);
    // 把上层注册的回调放入队列中，唤醒loop所在的线程执行回调
    void queueInLoop(Callback &&cb);

    // channel通过loop修改poller状态
    bool hasChannel(Channel *chan);
    void updateChannel(Channel *chan);
    void removeChannel(Channel *chan);

private:
    void handleWakeupFdRead(); // wakeFd绑定的回调，唤醒时执行，唤醒阻塞的epoll_wait
    void doPendingCallbacks(); // 执行上层回调

    // 所属线程id
    // 线程id比较可以判断loop是否属于当前线程
    const pid_t tid_;

    std::atomic_bool isStart_; // 开始loop
    std::atomic_bool isQuit_;  // 退出loop

    std::unique_ptr<Poller> poller_;
    Timestamp pollReturnTime_; // Poller返回就绪事件Channels的时间

    // 作用：当mainLoop获取一个新Channel，唤醒subLoop处理Channel
    // libevent用sockpair()网络通信唤醒
    // muduo用eventfd()线程间通信通知wakeupFd_相应的wakeupChannel_
    int wakeupFd_;
    std::unique_ptr<Channel> wakeupChan_;

    using ChannelVector = std::vector<Channel *>;
    ChannelVector activeChans_; // Poller返回就绪事件Channels

    std::atomic_bool hasPendingCallbacks_;   // 是否有需要执行的回调
    std::vector<Callback> pendingCallbacks_; // 需要执行的所有回调
    std::mutex mutex_;
};